﻿package 
{
	/**
	 * ...
	 * @author maximov
	 */
	import flash.geom.Vector3D;
	import jiglib.physics.constraint.JConstraintWorldPoint;
	import jiglib.physics.RigidBody;
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	
	/* Maze position controller.
	 * 
	 * It' impossible to create complex shapes in jiglib (or any other flash physics engine).
	 * So we have to control every wall of maze separatelly.
	 * 
	 * Besides Jiglib is not continues-state. So we can not directly set a body position without loosing collisions.
	 * And we have to create a constraint sealing for each controlled body.
	 */
	public  class Dragger 
	{
		//all constraints for walls
		private var draggers:Vector.<JConstraintWorldPoint>; 
		//original positions of the walls
		private var original_poses:Vector.<Vector3D>;
		//walls container for collisions disable
		private var bodies:Vector.<RigidBody>;
	
		// the shoulder lenght for constraint sealing
		private var arm:Number;
	
		public function Dragger()
		{
			draggers = new Vector.<JConstraintWorldPoint>(); 
			original_poses = new Vector.<Vector3D>(); 
			bodies = new Vector.<RigidBody>();
			arm = 70;
		}
		//add the body to the controlled group
		public function add(b:RigidBody):void
		{   
			//the sealing of the wall consist of center constraint and two shoulder constraints alligned to opposite axis.
			var pos:Vector3D = new Vector3D(b.x, b.y, b.z);
			var ax:Vector3D = new Vector3D(arm, 0, 0);
			var ay:Vector3D = new Vector3D(0, arm, 0);
			original_poses.push(pos, pos.add(ax), pos.add(ay));
			var nil:Vector3D = new Vector3D(0,0,0);
			var o:JConstraintWorldPoint = new  JConstraintWorldPoint(b, nil, pos);
			var x:JConstraintWorldPoint = new  JConstraintWorldPoint(b, ax, pos.add(ax) );
			var y:JConstraintWorldPoint = new  JConstraintWorldPoint(b, ay, pos.add(ay) );
			draggers.push(o, x, y);
			
			//add one additional constraint for the wall to avoid unstable configurations 
			var f:Vector3D = new Vector3D(arm, arm, arm);
			original_poses.push(pos.add(f));
			var xyz:JConstraintWorldPoint = new  JConstraintWorldPoint(b, f, pos.add(f) );
			draggers.push(xyz);

			//disable collisions beetween dragged walls
			for (var i:uint = 0; i < bodies.length; i++)
				{
				bodies[i].disableCollisions(b);
				b.disableCollisions(bodies[i]);
				}
			bodies.push(b);
		}
		public function addarray(bodies:Array):void
		{
			for ( var i:String in bodies)
				add(bodies[i]);
		}
		
		//set the desired position of controlled maze
		public function transform(m:Matrix3D):void
		{
			for (var i:uint = 0; i < draggers.length; i++)
			{
			
			var pos:Vector3D = original_poses[i];
			var new_pos:Number3D=new Number3D(pos.x,pos.y,pos.z)
			Matrix3D.multiplyVector(m,new_pos);
			draggers[i].worldPosition = new Vector3D(new_pos.x, new_pos.y, new_pos.z);
			}
		}
	}
	
}